/*
# Miahx© 框架消息 FastDDS API 的 Nodejs Addon 支持类（Nodejs端）

Version: 0.4.10,
Last updated: October 19, 2024

## Contributor(s)
* YAO Naiming <[naiming@iscas.ac.cn](mailto:naiming@iscas.ac.cn)>

## Change log
### v0.4.10
- .19: [更新] 新增对驾驶人意图数据的接收支持
- .17: [更新] 新增对自车轨迹数据的接收支持
### v0.4.7
- .26: [新增] 初始实现

Copyright (c) All contributors, ISCAS & ASIC. 2024.
All rights reserved. Licensed under Apache-2.0.
*/

#include <iostream>
#include <string>
#include <napi.h>
#include <miahx_nodejs_wrapper.h>

using namespace std;
using namespace Napi;


void on_data_available(const char *json, void *user_state) {
    auto json_clone = new string(json);
    assert(json_clone->size() > 0);
    assert(nullptr != user_state);

    // Call the callback function
    auto tsfn = (Napi::ThreadSafeFunction *) user_state;
    auto callback = [](Napi::Env env, Napi::Function jsCallback, string *cloned_json) {
        Napi::String nj_str = Napi::String::New(env, *cloned_json);
        jsCallback.Call({ nj_str });
        delete cloned_json;
    };
    napi_status status = tsfn->BlockingCall(json_clone, callback);
    if (status != napi_ok) {
        Napi::Error::Fatal("on_bng_cls_data_available", "status != napi_ok");
    }
}


class MiahxWrapperNodejsAddon : public Napi::ObjectWrap<MiahxWrapperNodejsAddon> {
public:
    static Napi::Object Init(Napi::Env env, Napi::Object exports) {
        Napi::Function func = DefineClass(env, "MiahxWrapperNodejsAddon", {
                InstanceMethod("destroy", &MiahxWrapperNodejsAddon::Destroy)
        });
        constructor = Persistent(func);
        constructor.SuppressDestruct();
        exports.Set("MiahxWrapperNodejsAddon", func);
        return exports;
    }

    MiahxWrapperNodejsAddon(const Napi::CallbackInfo &info)
            : Napi::ObjectWrap<MiahxWrapperNodejsAddon>(info) {
        // Reference: https://www.cnblogs.com/ajanuw/p/14404060.html
        Napi::Env env = info.Env();
        mTSFN = Napi::ThreadSafeFunction::New(
                env,                            // Environment
                info[0].As<Napi::Function>(),   // JS function from caller
                "name",                         // Resource name
                0,                              // Max queue size (0 = unlimited).
                1                               // Initial thread count
        );
        mWrapper = MiahxWrapperNodejs::get_instance();
        mWrapper->set_bng_classical_data_provider(on_data_available, &mTSFN);
        mWrapper->set_car_trajectory_data_provider(on_data_available, &mTSFN);
        mWrapper->set_usr_driver_intention_data_provider(on_data_available, &mTSFN);
    }

    ~MiahxWrapperNodejsAddon() {
        cout << "~MiahxWrapperNodejsAddon" << endl;
    }

private:
    void Destroy(const Napi::CallbackInfo &info) {
        mTSFN.Release();
    }

private:
    static FunctionReference constructor;
    Napi::ThreadSafeFunction mTSFN;
    MiahxWrapperNodejs *mWrapper;
};

FunctionReference MiahxWrapperNodejsAddon::constructor;

Object Init(Env env, Object exports) {
    MiahxWrapperNodejsAddon::Init(env, exports);
    return exports;
}

NODE_API_MODULE(miahx_support_nodejs, Init);